/*
 * $Id: iptc.h,v 1.37 2005-12-05 15:11:29 bacon Exp $
 */

#ifndef _XP_LNX_IPTC_H_
#define _XP_LNX_IPTC_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/net/ether.h>
#include <xp/lnx/libiptc.h>
#include <netinet/ether.h>

#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ipt_mac.h>
#include <linux/netfilter_ipv4/ipt_limit.h>
#include <linux/netfilter_ipv4/ipt_mark.h>
#include <linux/netfilter_ipv4/ipt_MARK.h>
#include <linux/netfilter_ipv4/ipt_REJECT.h>

typedef struct xp_iptc_t xp_iptc_t;
typedef struct ipt_entry xp_iptc_entry_t;

struct xp_iptc_t
{
        iptc_handle_t handle;
	xp_mchar_t table[IPT_TABLE_MAXNAMELEN];
	xp_bool_t loaded;

	xp_iptc_entry_t* entry;
	xp_size_t entry_capacity;
	
        xp_bool_t __dynamic;
};


/* basic ipt specifiction */
typedef struct xp_iptc_ipt_t xp_iptc_ipt_t;

enum 
{
	XP_IPTC_IPT_INVERSE_PROTO   = 1,
	XP_IPTC_IPT_INVERSE_SNET    = 2,
	XP_IPTC_IPT_INVERSE_DNET    = 4,
	XP_IPTC_IPT_INVERSE_IFCEIN  = 8,
	XP_IPTC_IPT_INVERSE_IFCEOUT = 16
};

struct xp_iptc_ipt_t
{
	int flags;
	int proto;

	struct 
	{
		xp_uint32_t ip;
		xp_uint32_t mask;
	} snet;

	struct 
	{
		xp_uint32_t ip;
		xp_uint32_t mask;
	} dnet;

	struct 
	{
		const xp_char_t* in;
		const xp_char_t* out;
	} ifce;
};

/* match definitions */
enum
{
	XP_IPTC_MATCH_TCP,
	XP_IPTC_MATCH_UDP,
	XP_IPTC_MATCH_MAC,
	XP_IPTC_MATCH_RATE,
	XP_IPTC_MATCH_MARK
};

enum
{
	XP_IPTC_MATCH_TCP_SPORT = 1,
	XP_IPTC_MATCH_TCP_DPORT = 2
};

enum
{
	XP_IPTC_MATCH_UDP_SPORT = 1,
	XP_IPTC_MATCH_UDP_DPORT = 2
};

typedef struct xp_iptc_match_t      xp_iptc_match_t;
typedef struct xp_iptc_match_tcp_t  xp_iptc_match_tcp_t;
typedef struct xp_iptc_match_udp_t  xp_iptc_match_udp_t;
typedef struct xp_iptc_match_mac_t  xp_iptc_match_mac_t;
typedef struct xp_iptc_match_rate_t xp_iptc_match_rate_t;
typedef struct xp_iptc_match_mark_t xp_iptc_match_mark_t;

struct xp_iptc_match_t
{
	xp_uint16_t id;
};

struct xp_iptc_match_tcp_t
{
	xp_uint16_t id; /* XP_IPTC_MATCH_TCP */
	int flags; /* XP_IPTC_MATCH_TCP_SPORT | XP_IPTC_MATCH_TCP_DPORT */

	struct 
	{
		xp_uint16_t start;
		xp_uint16_t end;
	} sport;

	struct 
	{
		xp_uint16_t start;
		xp_uint16_t end;
	} dport;
};


struct xp_iptc_match_udp_t
{
	xp_uint16_t id; /* XP_IPTC_MATCH_UDP */
	int flags; /* XP_IPTC_MATCH_UDP_SPORT | XP_IPTC_MATCH_UDP_DPORT */

	struct 
	{
		xp_uint16_t start;
		xp_uint16_t end;
	} sport;

	struct 
	{
		xp_uint16_t start;
		xp_uint16_t end;
	} dport;
};

struct xp_iptc_match_mac_t
{
	xp_uint16_t id;
	xp_byte_t smac[XP_ETHER_LEN]; 
};

struct xp_iptc_match_rate_t
{
	xp_uint16_t id;
	xp_uint32_t average;
	xp_uint32_t burst;
};

struct xp_iptc_match_mark_t
{
	xp_uint16_t id;
	unsigned long mark;
	unsigned long mask;
};

/* target definitions */
typedef struct xp_iptc_target_accept_t   xp_iptc_target_accept_t;
typedef struct xp_iptc_target_drop_t     xp_iptc_target_drop_t;
typedef struct xp_iptc_target_redirect_t xp_iptc_target_redirect_t;
typedef struct xp_iptc_target_reject_t   xp_iptc_target_reject_t;
typedef struct xp_iptc_target_snat_t     xp_iptc_target_snat_t;
typedef struct xp_iptc_target_dnat_t     xp_iptc_target_dnat_t;

enum
{
	XP_IPTC_TARGET_ACCEPT,
	XP_IPTC_TARGET_DROP,
	XP_IPTC_TARGET_REDIRECT,
	XP_IPTC_TARGET_REJECT,
	XP_IPTC_TARGET_SNAT,
	XP_IPTC_TARGET_DNAT
};

struct xp_iptc_target_accept_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_ACCEPT */
};

struct xp_iptc_target_drop_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_DROP */
};

struct xp_iptc_target_redir_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_REDIR */
	struct {
		xp_uint16_t start;
		xp_uint16_t  end;
	} port;
};

struct xp_iptc_target_reject_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_REJECT */
	xp_uint16_t type; 
};

struct xp_iptc_target_snat_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_SNAT */
	xp_uint16_t count;
	struct {
		xp_uint32_t start;
		xp_uint32_t end;
	} ip[1];
};

struct xp_iptc_target_dnat_t
{
	xp_uint16_t id; /* XP_IPTC_TARGET_DNAT */
	xp_uint16_t count;
	struct {
		int flags;
		struct {
			xp_uint32_t start;
			xp_uint32_t end;
		} ip;
		struct {
			xp_uint16_t start;
			xp_uint16_t end;
		} port;
	} range[1];
};

#ifdef __cplusplus
extern "C" {
#endif

xp_iptc_t* xp_iptc_open (xp_iptc_t* iptc, const xp_char_t* table_name);
void xp_iptc_close (xp_iptc_t* iptc);
int xp_iptc_commit (xp_iptc_t* iptc);
void xp_iptc_abort (xp_iptc_t* iptc);
int xp_iptc_reset (xp_iptc_t* iptc);

void xp_iptc_set_changed (xp_iptc_t* iptc);

int xp_iptc_create_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_delete_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_zero_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_flush_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_walk_chain (xp_iptc_t* iptc,
	int (*func) (xp_iptc_t*, const xp_char_t*));


const xp_iptc_entry_t* xp_iptc_first_rule (
        xp_iptc_t* iptc, const xp_char_t* name, 
	xp_iptc_entry_t const** rule_end);

const xp_iptc_entry_t* xp_iptc_next_rule (
        xp_iptc_t* iptc, const xp_iptc_entry_t* previous, 
	xp_iptc_entry_t const** rule_end);

int xp_iptc_insert_entry (
	xp_iptc_t* iptc, 
	const xp_char_t* chain_name, xp_size_t pos,
	const xp_char_t* target_name, 
	xp_bool_t inv_proto, int proto,
	xp_bool_t inv_src_ip, xp_uint32_t src_ip, xp_uint32_t src_mask,
	xp_bool_t inv_dst_ip, xp_uint32_t dst_ip, xp_uint32_t dst_mask,
	xp_bool_t inv_inifce, const xp_char_t* inifce,
	xp_bool_t inv_outifce, const xp_char_t* outifce,
	xp_bool_t inv_src_pt, xp_uint16_t src_pt_start, xp_uint16_t src_pt_end,
	xp_bool_t inv_dst_pt, xp_uint16_t dst_pt_start, xp_uint16_t dst_pt_end,
	int match_mac, const xp_byte_t src_mac[XP_ETHER_LEN],
	int match_rate, xp_uint32_t rate_avg, xp_uint32_t rate_burst,
	int match_mark, unsigned long mark, unsigned long mark_mask,
	int match_icmp, const xp_uint8_t icmp_info[3],
	xp_uint16_t redir_pt_start, xp_uint16_t redir_pt_end,
	unsigned long target_mark, int reject_type,
	xp_uint32_t snat_ip_start, xp_uint32_t snat_ip_end);

int xp_iptc_append_entry (
	xp_iptc_t* iptc, 
	const xp_char_t* chain_name,
	const xp_char_t* target_name, 
	xp_bool_t inv_proto, int proto,
	xp_bool_t inv_src_ip, xp_uint32_t src_ip, xp_uint32_t src_mask,
	xp_bool_t inv_dst_ip, xp_uint32_t dst_ip, xp_uint32_t dst_mask,
	xp_bool_t inv_inifce, const xp_char_t* inifce,
	xp_bool_t inv_outifce, const xp_char_t* outifce,
	xp_bool_t inv_src_pt, xp_uint16_t src_pt_start, xp_uint16_t src_pt_end,
	xp_bool_t inv_dst_pt, xp_uint16_t dst_pt_start, xp_uint16_t dst_pt_end,
	int match_mac, const xp_byte_t src_mac[XP_ETHER_LEN],
	int match_rate, xp_uint32_t rate_avg, xp_uint32_t rate_burst,
	int match_mark, unsigned long mark, unsigned long mark_mask,
	int match_icmp, const xp_uint8_t icmp_info[3],
	xp_uint16_t redir_pt_start, xp_uint16_t redir_pt_end,
	unsigned long target_mark, int reject_type,
	xp_uint32_t snat_ip_start, xp_uint32_t snat_ip_end);

int xp_iptc_delete_entry (
	xp_iptc_t* iptc, 
	const xp_char_t* chain_name,
	const xp_char_t* target_name, 
	xp_bool_t inv_proto, int proto,
	xp_bool_t inv_src_ip, xp_uint32_t src_ip, xp_uint32_t src_mask,
	xp_bool_t inv_dst_ip, xp_uint32_t dst_ip, xp_uint32_t dst_mask,
	xp_bool_t inv_inifce, const xp_char_t* inifce,
	xp_bool_t inv_outifce, const xp_char_t* outifce,
	xp_bool_t inv_src_pt, xp_uint16_t src_pt_start, xp_uint16_t src_pt_end,
	xp_bool_t inv_dst_pt, xp_uint16_t dst_pt_start, xp_uint16_t dst_pt_end,
	int match_mac, const xp_byte_t src_mac[XP_ETHER_LEN],
	int match_rate, xp_uint32_t rate_avg, xp_uint32_t rate_burst,
	int match_mark, unsigned long mark, unsigned long mark_mask,
	int match_icmp, const xp_uint8_t icmp_info[3],
	xp_uint16_t redir_pt_start, xp_uint16_t redir_pt_end,
	unsigned long target_mark, int reject_type,
	xp_uint32_t snat_ip_start, xp_uint32_t snat_ip_end);

int xp_iptc_delete_entry_at (
	xp_iptc_t* iptc, const xp_char_t* chain_name, xp_size_t pos);

#ifdef __cplusplus
}
#endif

#endif
